In any computing system, including general purpose computer systems and embedded systems, resource management generally and memory management in particular are very important to proper system operation. In any computing system, memory management typically occurs at several levels, e.g., hardware memory management, operating system (OS) memory management, and application memory management. OS and application memory management rely on various software techniques for allocation and deallocation of memory used by the system. In the OS, memory is allocated to user programs, and reused by other programs when it is no longer required. Application memory management typically involves supplying the memory needed for a program's objects and data structures from the limited resources available, and recycling that memory for reuse when it is no longer required.
In general, as memory allocation techniques have become more sophisticated, the nature of memory allocation errors have become more complex. For example, with static allocation (used in many early systems and in languages such as Fortran) all data structure names are bound to storage locations at compile-time and the bindings do not change at run-time. Although static allocation imposes significant limits on program flexibility, it reduces the complexity associated with debugging memory allocation errors. Various forms of dynamic memory allocation, both for stack memory and heap memory are more commonly used today. However, to support dynamic allocation, OS's and application programs utilize additional code to handle their changing memory requirements because they cannot in general predict in advance how much memory they are going to require. For example, when a program requests a block of memory, a memory manager will allocate that block out of the larger blocks it has received from the operating system. This allocation is performed by some combination of OS or kernel level memory management software and memory management software associated with the application itself, e.g., allocation and dealllocation functions such as the C functions malloc ( ) and free ( ).
One common form of memory allocation error is a memory leak, which can be a major resource issue leading to many system malfunctions and negative performance impacts. In general, a memory leak occurs when allocated memory is not freed after use, or when a needed reference to that allocated memory, e.g., a pointer to the memory allocation, is deleted thereby rendering the memory no longer reachable or “live” to the system. Memory leaks can take many forms, e.g. occurring in contiguous block or fragmentally, and can occur in a variety of different memory systems such as flattened memory architectures or those with virtual memory spaces. Reckless use of dynamic memory allocation can lead to memory management problems, which cause performance degradation, unpredictable execution or crashes.
Various tools currently exist to detect memory leaks. These tools typically work by replacing generic memory functions in the library, such as malloc ( ) and free ( ), and other memory calls with specialized functions designed to track and account for memory allocation. Each tool typically has code that intercepts calls to traditional memory functions during program execution and sets up logging information for each memory allocation/de-allocation request. Some tools can further implement memory protection fences to catch illegal memory accesses. In still other examples, the policing of memory allocation and de-allocation is performed by specialized programs generally referred to as garbage collectors.
Unfortunately, all of these techniques used to analyze software memory require source code instrumentation adding to the size and complexity of the source code. Moreover, such code instrumentation typically degrades program performance. In some cases, e.g., embedded systems, the impact may be so significant that it makes the program unusable in its planned environment. In still other cases, leak detection programs are so large that they require a virtual memory image of the program being analyzed, which can make their use very difficult. Many of the tools also present numerous “false positives,” that is they identify circumstances as memory leaks which are not in fact memory leaks.
Accordingly, it is desirable to have memory leak detection and analysis tools and methods that are compact, are less intrusive, pose low performance impact, are efficient, and present a low rate of false-positive results.